﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;


namespace CalculatorLogic
{
    public class TokenHelper
    {
        private const string _operators = "+-*/%=!^SINCOSTANLOGLNSECCSCCOT";
        private const string _leftAssociativeOperators = "*/%+-";
        private const string _rightAssociativeOperators = "!=^SINCOSTANLOGLNSECCSCCOT";

        private static readonly Dictionary<string, int> _operatorsToPrecedenceMapping =
            new Dictionary<string, int>
                {
                    {"=", 1},
                    {"+-", 2},
                    {"*/%", 3},
                    {"!", 4},
                    {"^SINCOSTANLOGLNSECCSCCOT", 5}
    };


        public bool IsOperator(string token)
        {
            
            if (IsNullOrWhiteSpace(token))
            {
                return false;
            }
            return _operators.Contains(token);
        }

        public int GetPrecedenceFor(string token)
        {
            foreach (KeyValuePair<string, int> precedenceMapping in _operatorsToPrecedenceMapping)
            {
                if (precedenceMapping.Key.Contains(token))
                {
                    return precedenceMapping.Value;
                }
            }
            throw new InvalidOperationException(string.Format("{0} is not a valid operator!", token));
        }

        public bool IsNumber(string token)
        {
            try
            {
                double result = double.Parse(token);
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        public bool IsFunction(string token)
        {
            char possibleFunction;
            try
            {
                possibleFunction = Convert.ToChar(token);
            }
            catch (Exception e)
            {
                return false;
            }
            return (possibleFunction >= 'A' && possibleFunction <= 'Z');
        }

        public bool IsLeftAssociative(string token)
        {
            if (IsNullOrWhiteSpace(token))
            {
                throw new ArgumentException("Incorrect token! Correct should be one character only", token);
            }
            return _leftAssociativeOperators.Contains(token);
        }

        public bool IsRightAssociative(string token)
        {
            if (IsNullOrWhiteSpace(token))
            {
                throw new ArgumentException("Incorrect token! Correct should be one character only", token);
            }
            return _rightAssociativeOperators.Contains(token);
        }

        public static bool IsNullOrWhiteSpace(string value)
        {
            if (value != null)
            {
                for (int i = 0; i < value.Length; i++)
                {
                    if (!char.IsWhiteSpace(value[i]))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
    }
}
